package org.thunms.schedule.quartz.service;

import java.io.Serializable;
import java.text.ParseException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javolution.util.FastList;
import javolution.util.FastMap;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronScheduleBuilder;
import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.thunms.framework.core.SpringContextHolder;
import org.thunms.framework.model.DataGrid;
import org.thunms.framework.model.DataGridJson;
import org.thunms.framework.quartz.QuartzJob;
import org.thunms.framework.utils.UtilDate;
import org.thunms.framework.utils.UtilDateTime;
import org.thunms.schedule.quartz.model.QrtzJobs;


/**
 * 工作任务引擎
 * 任务管理子系统
 * 平台任务列表
 */
@Service
public class QrtzJobsService implements Serializable  {
	private static final long serialVersionUID = 2061880167839248364L;
	private static final Logger logger = LoggerFactory.getLogger(QrtzJobsService.class);
	@Autowired
	@Qualifier("clusterQuartzScheduler")
	private Scheduler scheduler;
	private List<QrtzJobs> jobsList = FastList.newInstance();
	private Map<String, QrtzJobs> quartzJobsMap = FastMap.newInstance();
	private Map<String, QuartzJob> jobsMap = FastMap.newInstance();
	private Integer count = 0;
	private DataGridJson<QrtzJobs> dataGrid = new DataGridJson<QrtzJobs>();

	public DataGridJson<QrtzJobs> getDataGridList(DataGrid dg, QrtzJobs mode) {
		if (jobsList.isEmpty()) {
			Collection<QuartzJob> quartzJobs = SpringContextHolder.getBeans(QuartzJob.class);
			for (QuartzJob job : quartzJobs) {
				QrtzJobs qj = new QrtzJobs();
				qj.setName(job.getJobName());
				qj.setJobGroup(job.getJobGroup());
				qj.setJobClass(job.getJobClass().getName());
				qj.setDescription(job.getDescription());
				qj.setId(DigestUtils.md5Hex(qj.getJobClass()));//使用MD5加密类名作为key
				jobsList.add(qj);
				quartzJobsMap.put(qj.getId(), qj);
				jobsMap.put(qj.getId(), job);
				count++;
			}
			dataGrid.setRows(jobsList);
			dataGrid.setTotal(count.longValue());
		}

		return dataGrid;

	}

	public QrtzJobs getJob(String id) {
		return this.quartzJobsMap.get(id);
	}
	/**
	 * 高级任务添加
	 * @param jobsId 任务ID
	 * @param jobName 任务名称
	 * @param jobGroup 任务分组
	 * @param qrtzJobKey 业务ID
	 * @param cronExpression 定时脚本
	 * @param startTime  开始时间
	 * @param endTime 结束时间
	 * @return true添加成功、fasle添加失败
	 */
	public Boolean sdvancedAddSave(String jobsId, String jobName,String  jobGroup,String qrtzJobKey,String cronExpression,Date startTime,Date endTime) {
		
		if (StringUtils.isEmpty(jobsId)  ||StringUtils.isEmpty(cronExpression)) {
			return false;
		}
		try {
			if(!scheduler.isStarted()){
				scheduler.start();
			}
			Date start = null;
			if(startTime!=null){
				start=DateBuilder.evenSecondDate(startTime);
			}else{
				start=DateBuilder.evenSecondDate(UtilDateTime.nowDate());
			}
			Date end =null;  
			if(endTime!=null){
				end=DateBuilder.evenMinuteDate(endTime);
			}else{
				end=DateBuilder.evenMinuteDate(UtilDate.getYearStart(UtilDateTime.nowDate(), 0, 20));
			} 
			QrtzJobs qj=this.getJob(jobsId);
			if(StringUtils.isBlank(jobName)){
				jobName=qj.getName();
			}
			if(StringUtils.isBlank(jobGroup)){
				jobGroup=qj.getJobGroup();
			}
			JobBuilder jb=JobBuilder.newJob(jobsMap.get(jobsId).getClass())
					.withIdentity(jobName, jobGroup).requestRecovery();
			if(StringUtils.isNotBlank(qrtzJobKey)){
				JobDataMap newJobDataMap= new JobDataMap();
				newJobDataMap.put("qrtzJobKey", qrtzJobKey);
				jb.setJobData(newJobDataMap);
			}
			JobDetail job = jb.build();
			Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName,jobGroup)
					.startAt(start)
					.endAt(end)
					.withDescription(cronExpression)
			        .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))  
			        .build();  
			//scheduler.pauseAll();
			scheduler.scheduleJob(job, trigger);
			//scheduler.resumeAll();
			//scheduler.start();
			
		} catch (SchedulerException e) {
			logger.error("任务添加失败！", e);
			return false;
		}
		return true;
	}
	/**
	 * 执行测试
	 * @param jobsId 任务ID
	 * @param jobName 任务名称
	 * @param jobGroup 任务分组
	 * @param qrtzJobKey 业务ID
	 * @param startTime 开始时间
	 * @param endTime 结束时间
	 * @param repeatCount 执行次数
	 * @param repeatInterval 执行间隔
	 * @return true添加成功、fasle添加失败
	 */
	public Boolean simpleAddSave(String jobsId,String jobName,String  jobGroup,String qrtzJobKey,Date startTime, Date endTime, int repeatCount, int repeatInterval) {
		
		try {
			if(!scheduler.isStarted()){
				scheduler.start();
			}
			QrtzJobs qj=this.getJob(jobsId);
			Date start = null;
			if(startTime!=null){
				start=DateBuilder.evenSecondDate(startTime);
			}else{
				start=DateBuilder.evenSecondDate(UtilDateTime.nowDate());
			}
			Date end =null;  
			if(endTime!=null){
				end=DateBuilder.evenMinuteDate(endTime);
			}else{
				end=DateBuilder.evenMinuteDate(UtilDate.getYearStart(UtilDateTime.nowDate(), 0, 20));
			}
			SimpleScheduleBuilder simpleScheduleBuilder=SimpleScheduleBuilder.simpleSchedule();
			
			if(repeatCount>0){
				repeatCount=repeatCount-1;
			}
			//如果执行一次,应该是零
			simpleScheduleBuilder.withRepeatCount(repeatCount);//执行次数	
			//当执行间隔有效时，将不处理执行次数，当执行次数无效时默认执行1次
			if(repeatInterval==0){
				repeatInterval=60;
				
				
			}
			simpleScheduleBuilder.withIntervalInSeconds(repeatInterval);//间隔时间	
			
			
			if(StringUtils.isBlank(jobName)){
				jobName=qj.getName();
			}
			if(StringUtils.isBlank(jobGroup)){
				jobGroup=qj.getJobGroup();
			}
			
			JobBuilder jb = JobBuilder.newJob(jobsMap.get(jobsId).getClass())//设置任务类
					.withIdentity(jobName, jobGroup)//设置任务名称及任务分组信息
					.requestRecovery();
			if(StringUtils.isNotBlank(qrtzJobKey)){
				JobDataMap newJobDataMap= new JobDataMap();
				newJobDataMap.put("qrtzJobKey", qrtzJobKey);
				jb.setJobData(newJobDataMap);
			}
			JobDetail job = jb.build();
			Trigger trigger = TriggerBuilder.newTrigger()
					.startAt(start)
					.withIdentity(jobName,jobGroup)  
			        .withSchedule(simpleScheduleBuilder)
			        .endAt(end)
			        .withDescription("共执行"+repeatCount+"次,每次间隔"+repeatInterval+"秒")
			        .build();  
			//scheduler.pauseAll();
			scheduler.scheduleJob(job, trigger);
			//scheduler.resumeAll();
			} catch (SchedulerException e) {
				logger.error("任务添加失败！", e);
				return false;
			}
		return true;
		
	}
	/**
	 * 周期间隔执行任务
	 * @param jobsId 任务ID
	 * @param jobName 任务名称
	 * @param jobGroup 任务分组
	 * @param qrtzJobKey 业务ID
	 * @param val 间隔时间
	 * @param selType second、minute、hour间隔秒、分钟、小时周期执行
	 * @param startTime 开始时间
	 * @param endTime 结束时间
	 * @return true添加成功、fasle添加失败
	 */
	public Boolean periodAddSave(String jobsId,String jobName,String  jobGroup,String qrtzJobKey, Integer val, String selType,Date startTime,Date endTime) {
		if (StringUtils.isEmpty(jobsId)  || val < 0 || val> 59) {
			return false;
		}
		QrtzJobs qj=this.getJob(jobsId);
		try {
			if(!scheduler.isStarted()){
				scheduler.start();
			}
			
			String expression = null;
			if (StringUtils.equals(selType, "second")) {
				// 每多秒执行一次
				expression = "0/" + val + " * * ? * * *";
			} else if (StringUtils.equals(selType, "minute")) {
				// 每多少分执行一次
				expression = "0 0/" + val + " * ? * * *";
			}else if(StringUtils.equals(selType, "hour")){
				// 每多少小时执行一次
				expression = "0 0 0/" + val + " ? * * *";
			}
			Date start = null;
			if(startTime!=null){
				start=DateBuilder.evenSecondDate(startTime);
			}else{
				start=DateBuilder.evenSecondDate(UtilDateTime.nowDate());
			}
			Date end =null;  
			if(endTime!=null){
				end=DateBuilder.evenMinuteDate(endTime);
			}else{
				end=DateBuilder.evenMinuteDate(UtilDate.getYearStart(UtilDateTime.nowDate(), 0, 20));
			}
			
			if(StringUtils.isBlank(jobName)){
				jobName=qj.getName();
			}
			if(StringUtils.isBlank(jobGroup)){
				jobGroup=qj.getJobGroup();
			}
			
			JobBuilder jb = JobBuilder.newJob(jobsMap.get(jobsId).getClass()).withIdentity(jobName, jobGroup).requestRecovery();
			
			if(StringUtils.isNotBlank(qrtzJobKey)){
				JobDataMap newJobDataMap= new JobDataMap();
				newJobDataMap.put("qrtzJobKey", qrtzJobKey);
				jb.setJobData(newJobDataMap);
			}
			JobDetail job = jb.build();
			  
			Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName,jobGroup)
					.startAt(start)
					.endAt(end)
					.withDescription(expression)
			        .withSchedule(CronScheduleBuilder.cronSchedule(expression))  
			        .build();
			//scheduler.pauseAll();
			scheduler.scheduleJob(job, trigger);
			//scheduler.resumeAll();
			
		} catch (SchedulerException e) {
			logger.error("任务添加失败",e);
			return false;
		} 
		return true;
		
	}
	/**
	 * 判断是否已经存在定时任务
	 * @param jobName 任务名称
	 * @param jobGroup 任务分组
	 * @return true存在、fasle不存在
	 */
	public Boolean JobExist(String jobName,String  jobGroup){
		try {
			return scheduler.checkExists(new JobKey(jobName, jobGroup));
		} catch (SchedulerException e) {
			logger.error("检查是否存在",e);
		}
		return true;
	}

}
